<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of DAO
 *
 * @author Administrador
 */
class DAO {
    	private static $url;            // Local do banco de dados
	private static $user;           // Usuario do banco de dados
	private static $pass;           // Senha do banco de dados
	private static $dbname;         // Nome do banco de dados
	
	private static $conn;           // Conexao com o BD
	private static $result;         // Resultado da ultima consulta
	private static $debug = true;  // Controla se o debug esta ativo ou nao - quando true toda query enviado ao BD é mostrado na tela
    private static $begin = false;  // Define se uma transação está ou não ativa
    
    public static $escape = true;   // Define se a query deve ou não escapar as strings
	
    // Seta a configuração para conectar no banco de dados
	public static function setConfig($url, $user, $pass, $dbname){
		self::$url    = $url;
		self::$user   = $user;
		self::$pass   = $pass;
		self::$dbname = $dbname;
	}
	
    // Conecta com o banco de dados
	public static function connect(){
        if(empty(self::$conn)){
            /* Connect to an ODBC database using driver invocation */
            $dsn = 'pgsql:host='.self::$url.';dbname='.self::$dbname;
            $user = self::$user;
            $password = self::$pass;

            try {
                self::$conn = new PDO($dsn, $user, $password);
                
                // Atualizando o timestamp do server
                $now = new DateTime("2012-09-27 23:38:20", new DateTimeZone('America/Sao_Paulo'));  
                $mins = $now->getOffset() / 60; 
                $sgn = ($mins < 0 ? -1 : 1);  
                $mins = abs($mins);  
                $hrs = floor($mins / 60);  
                $mins -= $hrs * 60;
                $offset = sprintf('%+d:%02d', $hrs*$sgn, $mins); 
                
                self::$conn->exec("SET time_zone='$offset';"); 
                self::$conn->exec("SET NAMES 'utf8'");
                self::$conn->exec('SET character_set_connection=utf8');
                self::$conn->exec('SET character_set_client=utf8');
                self::$conn->exec('SET character_set_results=utf8');
            } catch (PDOException $e) {
                print '<h3 clas="erro">Falha na Conexão: ' . $e->getMessage() . "</h3>";
            }
        }
        return self::$conn;
	}
	
    // Prepara a consulta e executa no banco de dados, retornando o objeto da execução
    private static function prepareAndExecute($sql, $args){
        
        // Escapando os dados
        for($i = 0; $i < count($args); $i++){
            if(is_numeric($args[$i]) || empty($args[$i])) continue;
            if(self::$escape)
                $args[$i] = self::escape($args[$i]);
            else
                $args[$i] = pgsql_real_escape_string($args[$i]);
        }
        
        // Preparando a query
        $dbh = self::connect();
        $sth = $dbh->prepare($sql);
        self::$result = $sth;
        
        // Exibindo o log
        self::show("SQL: ".$sql."<br />",$args);
        
        // Executando a query
        if (!$sth->execute($args)) {
            if(self::$debug){
                print("<h3 clas='erro'>Query invalida</h3>Especificação do erro: " . implode("</li><li>",$sth->errorInfo()));
            }
            return false;
		}
        
        // Retornando o objeto de execução
        return $sth;
    }
    
    // Executa um SQL no banco de dados
	public static function execute($sql, $args=array()){
        return self::prepareAndExecute($sql, $args);
	}
	
    // Retrona o numero de linhas afetadas/encontradas na ultima consulta
	public static function getNumRows(){
        if(!empty(self::$result))
            return self::$result->rowCount();
        else
            return 0;
	}
	
    // Retorna os dados para uma consulta SQL
	public static function get($sql, $args=array()){
        $lin = 0;
        $dados = array();
        $sth = self::prepareAndExecute($sql, $args);
        while( $linha = $sth->fetch(PDO::FETCH_BOTH) ){
            foreach($linha as $id => $val ){
                $dados[$lin][$id] = $val;
            }
            $lin++;
        }
        return $dados;
	}
	
    // Retorna uma linha para uma consulta SQL
	public static function getRow($sql, $args=array()){
        $sth = self::prepareAndExecute($sql, $args);
		return $sth->fetch(PDO::FETCH_BOTH);
	}
	
    // Retorna um valor para uma consulta SQL
	public static function getField($sql, $args=array()){
        $sth = self::prepareAndExecute($sql, $args);
		list($v) = $sth->fetch(PDO::FETCH_BOTH);
		return $v;
	}
	
    // Retorna a chave primaria da ultima inserção de uma tabela que tem chave auto increment
	public static function getId($nameid=null){
        $dbh = self::connect();
		if (empty($nameid))
			return null;
		else
			return $dbh->lastInsertId($nameid);
	}
	
    // Ativa ou desativa o modo DEBUG
	public static function debug(){
		self::$debug = !self::$debug;
		self::show("DEBUG ATIVADO");
	}
	
    // Mostra uma query SQL quando o debug esta ativo
	public static function show($sql, $args=""){
		if(self::$debug){
			print "<hr /><pre>".$sql;
            if(!empty($args))
                var_dump($args);
            print "</pre>";
            
		}
	}
	
    // Começa uma transação com o BD
	public static function begin(){
        $dbh = self::connect();
        if(!self::$begin){
            self::show("BEGIN");
            $dbh->beginTransaction();
            self::$begin = true;
        }
	}
	
    // Commita uma transação com o BD
	public static function commit(){
        if(self::$begin){
            self::show("COMMIT");
            self::$conn->commit();
            self::$begin = false;
        }
	}
	
    // Realiza o rollback com o BD 
	public static function rollback(){
        if(self::$begin){
            Query::show("ROLLBACK");
            self::$conn->rollBack();
            self::$begin = false;
        }
	}
	
	// Escapa um texto dos caracteres especiais do HTML
	public static function unHtmlEntities ($string){
		$trans_tbl = get_html_translation_table(HTML_ENTITIES);
		$trans_tbl = array_flip($trans_tbl);
		return strtr($string, $trans_tbl);
	}
   
	// Escapa o texto contra ataques do tipo sqlinjection
	public static function escape($string){
		return self::unHtmlEntities(pg_escape_string($string));
	}

}

?>
